#include "../Mocker.h"

namespace MockItNow
{
	int g_jumpAddress;

	extern "C" void __declspec(naked) _penter()
	{
		// Prologue
		__asm
		{
			push ebp
			mov ebp, esp
			sub esp, __LOCAL_SIZE
			push eax
			push ebx
			push ecx
			push edx
		}

		int* framePointer;
		__asm mov dword ptr [framePointer], ebp

		int targetPointer;
		__asm mov [targetPointer], ecx

		{
			int callingFunctionAddress = (*(framePointer + 1) - 5);

			if (Mocker::IsAlive() == false || Mocker::Instance().ShouldStubFunction(callingFunctionAddress, targetPointer) == false)
			{
				// Standard epilogue. Don't stub the function
				__asm
				{
					pop edx
					pop ecx
					pop ebx
					pop eax
					mov esp, ebp
					pop ebp
					ret
				}
			}

			Mocker::Instance().SetCurrentFunctionAddress(callingFunctionAddress);

			g_jumpAddress = Mocker::Instance().GetFunctionJumpAddress();

			// Non-standard epilogue. Stub the function
			__asm
			{
				pop edx
				pop ecx
				pop ebx
				pop eax
				mov esp, ebp
				pop ebp
				add esp, 4
				jmp g_jumpAddress
			}
		}
	}
}